#ifndef _NETUTILS_H
#define _NETUTILS_H

#include "config.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

/** byte size of ip4 address */
#define INET_SIZE 4
/** byte size of ip6 address */
#define INET6_SIZE 16

size_t get_sockaddr_len(struct sockaddr *addr);
ssize_t get_sockaddr(char *host, char *port,
	struct sockaddr_storage *storage, int block);
int set_reuseport(int socket);
int bind_to_address(int socket_fd, const char *address);

/**
 * Compare two sockaddrs. Imposes an ordering on the addresses.
 * Compares address and port.
 * @param addr1: address 1.
 * @param addr2: address 2.
 * @param len: lengths of addr.
 * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger.
 */
int sockaddr_cmp(struct sockaddr_storage *addr1,
	struct sockaddr_storage *addr2, socklen_t len);

/**
 * Compare two sockaddrs. Compares address, not the port.
 * @param addr1: address 1.
 * @param addr2: address 2.
 * @param len: lengths of addr.
 * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger.
 */
int sockaddr_cmp_addr(struct sockaddr_storage *addr1,
	struct sockaddr_storage *addr2, socklen_t len);
int setnonblocking(int fd);
int create_and_bind(const char *addr, const char *port);
int create_and_connect(const char *addr, const char *port);
int create_and_connect_noblock(const char *addr, const char *port, int *ret);
int ipv4_private_addr(in_addr_t addr);
int host_private_addr(char *host, size_t hostlen);
int tcp_alive(int sock);

#ifdef CONNLOG
typedef struct dst {
	uint8_t addrtype;
	union {
		struct sockaddr_storage storage;
		struct {
			uint8_t hostlen;
			char	host[257];
			uint16_t port;
		} host;
	};
} dst_t;

void _sys_info_addr(char *file, int line, char *fmt, struct dst *dst);
#define sys_info_addr(fmt, server)	\
	do {				\
		if(server)		\
			_sys_info_addr(__FILE__, __LINE__, fmt, &(server->dst)); \
	} while(0)
#else
#define sys_info_addr(fmt, server)	NULL
#endif
#endif /* _NETUTILS_H */
